package com.eyewind.myapplication

import android.content.Context
import android.graphics.Rect
import android.support.v7.widget.LinearLayoutManager
import android.support.v7.widget.LinearSmoothScroller
import android.support.v7.widget.RecyclerView
import android.util.AttributeSet
import android.util.DisplayMetrics
import android.view.View
import android.view.animation.Interpolator
import android.widget.OverScroller
import com.tjbaobao.framework.base.BaseApplication
import com.tjbaobao.framework.utils.DeviceUtil
import com.tjbaobao.framework.utils.Tools
import java.lang.Exception

@Suppress("unused")
class ViewPagerRecyclerView : RecyclerView {

    private var marginLeft = Tools.dpToPx(8)
    private var marginItem = Tools.dpToPx(3)
    private var offsetX = 0
    private var itemWidth = DeviceUtil.getScreenWidth()-(marginLeft+marginItem)*2

    constructor(context : Context) : this(context,null)

    constructor(context: Context,attrs : AttributeSet?) : this(context,attrs,0)

    constructor(context: Context,attrs: AttributeSet?,defStyleAttr : Int) : super(context,attrs,defStyleAttr)

    init {
        try {
            val mViewFlingerField = RecyclerView::class.java.getDeclaredField("mViewFlinger")
            mViewFlingerField.isAccessible = true
            val mViewFlinger = mViewFlingerField.get(this)
            val mScrollerField = mViewFlinger.javaClass.getDeclaredField("mScroller")
            mScrollerField.isAccessible = true
            mScrollerField.set(mViewFlinger,MyOverScroller(context,MyInterpolator()))
        }catch (e:Exception){
        }
        layoutManager = LinearLayoutManager(context, LinearLayoutManager.HORIZONTAL, false)
        addItemDecoration(SpaceItem())
        addOnScrollListener(OnScrollChangeListener())
    }


    private inner class OnScrollChangeListener : RecyclerView.OnScrollListener() {
        private var dx: Int = 0
        override fun onScrolled(recyclerView: RecyclerView?, dx: Int, dy: Int) {
            this.dx = dx
            isScrollSlow = Math.abs(dx) < 100
            offsetX += dx
        }
        override fun onScrollStateChanged(recyclerView: RecyclerView?, newState: Int) {
            when (newState) {
                RecyclerView.SCROLL_STATE_SETTLING -> isScrolling = true
                RecyclerView.SCROLL_STATE_DRAGGING, RecyclerView.SCROLL_STATE_IDLE -> {
                    if(newState==RecyclerView.SCROLL_STATE_IDLE){
                        val layoutManager = recyclerView!!.layoutManager
                        if (layoutManager is LinearLayoutManager) {
                            val position = layoutManager.findFirstVisibleItemPosition()
                            if (dx > 0) {
                                if (position + 1 < adapter.itemCount) {
                                    smoothScroller.targetPosition = position + 1
                                } else {
                                    smoothScroller.targetPosition = position
                                }
                            } else {
                                smoothScroller.targetPosition = position
                            }
                            recyclerView.layoutManager.startSmoothScroll(smoothScroller)
                        }
                    }
                    if (isScrolling) {
                        adapter.notifyDataSetChanged()
                    }
                    isScrolling = false
                }
            }
        }
    }

    internal var smoothScroller: RecyclerView.SmoothScroller = object : LinearSmoothScroller(BaseApplication.getContext()) {
        override fun getVerticalSnapPreference(): Int {
            return LinearSmoothScroller.SNAP_TO_START
        }

        override fun calculateSpeedPerPixel(displayMetrics: DisplayMetrics): Float {
            return 0.1f
        }
    }

    inner class MyOverScroller(context: Context?, interpolator: Interpolator?) : OverScroller(context, interpolator)
    {
        override fun fling(startX: Int, startY: Int, velocityX: Int, velocityY: Int, minX: Int, maxX: Int, minY: Int, maxY: Int) {
            var offset:Int?=null
            val velocity=Math.pow(Math.abs(velocityX).toDouble(),0.9).toInt()*(if (velocityX>0)1 else -1)
            val distance=getSplineFlingDistance(this,velocity)
            val actualDis:Int
            if(velocityX>0){
                actualDis=offsetX+distance
                val visiblePos=(layoutManager as LinearLayoutManager).findFirstVisibleItemPosition()
                for (i in visiblePos..(adapter.itemCount-1)){
                    val dis=getItemOffsetOfPos(i)
                    if(actualDis<=dis){
                        offset=dis-offsetX
                        break
                    }
                }
            }else{
                actualDis=offsetX-distance
                val visiblePos=(layoutManager as LinearLayoutManager).findLastVisibleItemPosition()
                for (i in visiblePos downTo 0){
                    val dis=getItemOffsetOfPos(i)
                    if(actualDis>=dis){
                        offset=dis-offsetX
                        break
                    }
                }
            }
            super.fling(startX, startY, velocity, velocityY, offset?:minX, offset?:maxX, minY, maxY)
        }

        private fun getSplineFlingDistance(mScroller:OverScroller,velocity:Int):Int{
            val field = OverScroller::class.java.getDeclaredField("mScrollerX")
            field.isAccessible = true
            val mScrollerX = field.get(mScroller)

            val method=mScrollerX.javaClass.getDeclaredMethod("getSplineFlingDistance", Int::class.java)
            method.isAccessible=true
            return (method.invoke(mScrollerX, velocity) as Double).toInt()
        }
    }

    private var isScrolling: Boolean = false
    private var isScrollSlow: Boolean = false
    private inner class OnItemScrollListener : RecyclerView.OnScrollListener() {

        override fun onScrollStateChanged(recyclerView: RecyclerView?, newState: Int) {
            when (newState) {
                RecyclerView.SCROLL_STATE_SETTLING -> isScrolling = true
                RecyclerView.SCROLL_STATE_DRAGGING, RecyclerView.SCROLL_STATE_IDLE -> {
                    if(newState==RecyclerView.SCROLL_STATE_IDLE){
                        val visiblePos=(layoutManager as LinearLayoutManager).findFirstVisibleItemPosition()
                        val endPos=Math.min(visiblePos+2,adapter.itemCount-1)
                        val idle= (visiblePos..endPos).any { offsetX==getItemOffsetOfPos(it) }
                        if(!idle){
                            val offset1=getItemOffsetOfPos(visiblePos)-offsetX
                            val offset2=getItemOffsetOfPos(visiblePos+1)-offsetX
                            val offset=if(Math.abs(offset1)<Math.abs(offset2)) offset1 else offset2
                            if(offset!=0){
                                smoothScrollBy(offset,0)
                                return
                            }
                        }
                    }
                    if (isScrolling) {
                        adapter.notifyDataSetChanged()
                    }
                    isScrolling = false
                }
            }
        }

        override fun onScrolled(recyclerView: RecyclerView?, dx: Int, dy: Int) {
            isScrollSlow = Math.abs(dx) < 100
            offsetX += dx
        }
    }

    private inner class SpaceItem : RecyclerView.ItemDecoration() {

        override fun getItemOffsets(outRect: Rect, view: View, parent: RecyclerView, state: RecyclerView.State?) {
            val pos = parent.getChildAdapterPosition(view)
            outRect.left = if (pos == 0) marginLeft else marginItem
            outRect.right = if (pos == parent.adapter.itemCount - 1) marginLeft else marginItem

        }
    }

    //内部类需要加上inner
    inner class MyInterpolator : Interpolator
    {
        override fun getInterpolation(input: Float): Float {
            var t = input
            t -= 1.0f
            t * t * t * t * t + 1.0f
            return t
        }
    }

    private fun getItemOffsetOfPos(pos:Int):Int{
        return when {
            pos==0 -> 0
            pos<adapter.itemCount-1 -> itemWidth+(pos-1)*(itemWidth+marginItem*2)
            pos==adapter.itemCount-1 -> pos*(itemWidth+marginItem*2)
            else -> 1
        }
    }

    fun setMargin(marginLeft:Int,marginItem:Int):Int
    {
        itemWidth = DeviceUtil.getScreenWidth()-(marginLeft+marginItem)*2
        return itemWidth
    }

    fun getItemWidth() : Int{
        return itemWidth
    }

    companion object {
        fun getItemWidthStatic() : Int{
            return DeviceUtil.getScreenWidth()-( Tools.dpToPx(8)+ Tools.dpToPx(3))*2
        }
    }

}